Skip to content

Conversation

@GeorgeLeePatterson
Copy link

Summary

Fixes a critical issue where the federation optimizer panics when processing LogicalPlan::Unnest nodes due to DataFusion's inconsistent behavior with expressions() vs with_new_exprs().

Problem

The federation optimizer would crash with:

plan.with_new_exprs(new_expressions, new_inputs)?

because LogicalPlan::Unnest.expressions() returns expressions but with_new_exprs() rejects them in the case of LogicalPlan::Unnest(_).

Solution

  • Add special case handling for LogicalPlan::Unnest in optimize_plan_recursively
  • Pass empty expressions vector for Unnest plans instead of plan.expressions()
  • This follows the same pattern used by other DataFusion optimizers

Testing

  • ✅ Added unit test test_federation_optimizer_rule_handles_unnest
  • ✅ Added integration example df-unnest.rs demonstrating cross-database federation with unnest
  • ✅ Verified fix works with actual federated queries

Checklist

  • Tests added/updated
  • Example demonstrates the fix
  • No breaking changes
  • Follows existing code patterns

Next Steps

Will also create a follow up PR with DataFusion with a possible solution to the underlying problem. If that gets merged I will come back and clean this up.

Fix critical issue where Unnest LogicalPlan.expressions() returns expressions
but with_new_exprs() rejects them, causing federation optimizer to panic.

- Add special case in optimize_plan_recursively to pass empty expressions
  for LogicalPlan::Unnest instead of plan.expressions()
- Add comprehensive test demonstrating federated unnest across multiple engines
- Add regression test for FederationOptimizerRule.rewrite handling Unnest plans

This enables proper federation of queries containing unnest operations.
@GeorgeLeePatterson
Copy link
Author

@hozan23 @trueleo Checking in to see if you had a chance to review this PR.

@hozan23
Copy link
Collaborator

hozan23 commented Jul 19, 2025

Hello @GeorgeLeePatterson, Thanks for this PR

I think we should consider holding off on merging this for now and instead wait for a proper fix upstream in DataFusion itself. Not a big fan of adding special-case handling directly into the optimizer, it can make the logic harder to read & reason about over time

Let's wait the upstream fix and revisit this once it's available

@trueleo Maybe we can get your thoughts on this as well?

@GeorgeLeePatterson
Copy link
Author

@hozan23 Thank you for the reply. That makes sense, I can continue operating on my fork for now in the context of an upcoming crate I am releasing. I have code locally with the fix for DataFusion. If your goal is to benefit from the upstream fix first, then I can shift my focus in that direction and see if I can get the fix merged on the DataFusion side. I appreciate the response and let me know if there's anything else here that is of use. If you do decide to merge it, I will be posting a PR for the DataFusion fix regardless and would be happy to track it to ensure this library gets updated as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants